package controller;

import entity.FileSystem;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.io.File;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 视频上传
 * @author wanggege
 */
@Controller
public class FileAction {

    @Autowired
    private Redisson redisson;

    @Bean
    public Redisson redisson(){
        Config config = new Config();
        // 使用单个redis服务器
        config.useSingleServer().setAddress("redis://192.168.32.130:6379").setDatabase(0);
        // 使用集群redis
        // config.useClusterServers().setScanInterval(2000).addNodeAddress("redis://192.168.204.141:6379","redis://192.168.204.142:6379","redis://192.168.204.143:6379");
        return (Redisson)Redisson.create(config);
    }

    @RequestMapping("/upload")
    public String upload(Model model, MultipartHttpServletRequest request) throws Exception{

        // 从页面请求中，获取上传的文件对象
        MultipartFile file = request.getFile("fname");

        /*加锁*/
        String lockName = "videoLock";
        // 通过redisson获取锁
        RLock rLock = redisson.getLock(lockName); // 底层源码就是集成了setnx，过期时间等操作
        // 上锁（过期时间为30秒）
        rLock.lock(30, TimeUnit.SECONDS);

        FileSystem fileSystem = null;

        try {
            fileSystem = uploadFileToFastDfs(file);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 释放锁
            rLock.unlock();
        }

        /*不加锁*/
//        FileSystem fileSystem = uploadFileToFastDfs(file);

        model.addAttribute("fileSystem",fileSystem);
        return  "index";
    }


    /**
     *
     * 上传文件的流程：
     *   1、先把文件保存到web服务器上
     *   2、再从web服务器上将文件 上传 到 FastDFS上
     * @param file 待上传的文件
     * @return 上传文件对象的json对象
     * @throws Exception
     */
    public FileSystem uploadFileToFastDfs(MultipartFile file) throws Exception{

        FileSystem fileSystem = new FileSystem();

        /* 1、把文件保存到web服务器*/

        // 从文件对象中获取 文件的原始名称
        String originalFilename = file.getOriginalFilename();
        // 通过字符串截取的方式，从文件原始名中获取文件的后缀
        String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        // 为了避免文件因为同名而覆盖，生成全新的文件名
        String newFileName = UUID.randomUUID().toString() + "." + suffix;
        // 创建web服务器保存文件的目录
        File toSaveFile = new File("/Users/wanggege/Desktop/upload/" + newFileName);
        // 将路径转换成文件
        file.transferTo(toSaveFile);
        // 获取服务器的绝对路径
        String newFilePath = toSaveFile.getAbsolutePath();

        //模拟网络延迟
        Thread.sleep(1000);

        /* 2、把文件从web服务器上传到FastDFS*/

        // 加载配置文件
        ClientGlobal.initByProperties("config/fastdfs-client.properties");
        // 创建tracker客户端
        TrackerClient trackerClient = new TrackerClient();
        // 通过tracker客户端获取tracker的连接服务并返回
        TrackerServer trackerServer = trackerClient.getConnection();
        // 声明storage服务
        StorageServer storageServer = null;
        // 定义storage客户端
        StorageClient1 client = new StorageClient1(trackerServer, storageServer);

        // 定义文件元信息
        NameValuePair[] list = new NameValuePair[1];
        list[0] = new NameValuePair("fileName",originalFilename);

        String fileId = client.upload_file1(newFilePath, suffix, list);
        System.out.println(fileId);

        // 封装fileSystem数据对象
        fileSystem.setFileId(fileId);
        fileSystem.setFileName(originalFilename);
        fileSystem.setFilePath(fileId);

        return fileSystem;
    }

}
